package beer.xz.beer.device.comm.protocol

import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.*

/**
 * 啤酒机协议实现
 * 根据CSV文件中的上报数据格式实现解码功能
 */
class BeerProtocolImpl {
    companion object {
        // 协议常量
        const val HEADER_BYTE: Byte = 0x0F.toByte()  // 数据头
        const val TAIL_BYTE1: Byte = 0x0D.toByte()   // 数据尾1
        const val TAIL_BYTE2: Byte = 0x0A.toByte()   // 数据尾2

        // 数据长度 (固定180字节的数据域)
        const val DATA_LENGTH = 180

        // 长度字段的字节数
        const val LENGTH_FIELD_SIZE = 3

        // 总包长度 (头部1字节 + 长度3字节 + 数据域180字节 + 校验和1字节 + 尾部2字节)
        const val TOTAL_PACKET_SIZE = 1 + LENGTH_FIELD_SIZE + DATA_LENGTH + 1+1 + 2

        // 数据字段地址偏移量
        private const val OFFSET_TEMPERATURE = 4  // 头部1字节 + 长度3字节
        private const val OFFSET_WEIGHT1 = 5
        private const val OFFSET_WEIGHT2 = 9
        private const val OFFSET_WEIGHT3 = 13
        private const val OFFSET_WEIGHT4 = 17
        private const val OFFSET_MOTOR_POSITION = 21
        private const val OFFSET_FLOW_COUNT = 25
        private const val OFFSET_RUNNING_TIME = 37
        private const val OFFSET_INPUT_SWITCH_FLAGS = 117
        private const val OFFSET_HARDWARE_FAULT = 161
        private const val OFFSET_SOFTWARE_FAULT = 165
        private const val OFFSET_DEVICE_ID = 169
        private const val OFFSET_SOFTWARE_VERSION = 173
        private const val OFFSET_HARDWARE_VERSION = 177
        private const val OFFSET_RELAY_OUTPUT = 181
        private const val OFFSET_RUNNING_FLAG = 183
        private const val OFFSET_DATA_TYPE = 184
        const val OFFSET_CHECKSUM = 185
    }

    /**
     * 解码数据包
     * @param data 原始数据包
     * @return 解析后的BeerMachineStatus对象，如果数据无效则返回null
     */
    fun decodeData(data: ByteArray): BeerMachineStatus? {
        // 检查数据长度
        if (data.size != TOTAL_PACKET_SIZE) {
            println("数据长度错误: 期望 $TOTAL_PACKET_SIZE 字节, 实际 ${data.size} 字节")
            return null
        }

        // 检查头部和尾部
        if (data[0] != HEADER_BYTE) {
            println("头部错误: 期望 0x${HEADER_BYTE.toInt() and 0xFF}, 实际 0x${data[0].toInt() and 0xFF}")
            return null
        }

        if (data[data.size - 2] != TAIL_BYTE1 || data[data.size - 1] != TAIL_BYTE2) {
            println("尾部错误: 期望 0x${TAIL_BYTE1.toInt() and 0xFF} 0x${TAIL_BYTE2.toInt() and 0xFF}, 实际 0x${data[data.size - 2].toInt() and 0xFF} 0x${data[data.size - 1].toInt() and 0xFF}")
            return null
        }

        // 检查校验和
        val calculatedChecksum = calculateChecksum(data)
        if (calculatedChecksum != data[OFFSET_CHECKSUM]) {
            println("校验和错误: 期望 0x${data[OFFSET_CHECKSUM].toInt() and 0xFF}, 计算得到 0x${calculatedChecksum.toInt() and 0xFF}")
            return null
        }

        // 打印数据包内容（调试用）
        printPacket(data)

        try {
            // 使用ByteBuffer解析数据
            val buffer = ByteBuffer.wrap(data)
            buffer.order(ByteOrder.LITTLE_ENDIAN)

            // 读取温度 (1字节)
            buffer.position(OFFSET_TEMPERATURE)
            val temperature = buffer.get().toInt() and 0xFF

            // 读取重量数据 (各4字节浮点数)
            buffer.position(OFFSET_WEIGHT1)
            val beerBottleWeight = buffer.getFloat()

            buffer.position(OFFSET_WEIGHT2)
            val outputBeerWeight = buffer.getFloat()

            buffer.position(OFFSET_WEIGHT3)
            val bottlePressure = buffer.getFloat()

            buffer.position(OFFSET_WEIGHT4)
            val co2Pressure = buffer.getFloat()

            // 读取电机和流量数据 (各4字节浮点数)
            buffer.position(OFFSET_MOTOR_POSITION)
            val motorPosition = buffer.getFloat()

            buffer.position(OFFSET_FLOW_COUNT)
            val flowCount = buffer.getFloat()

            // 读取运行时间 (8字节长整型)
            buffer.position(OFFSET_RUNNING_TIME)
            val runningTimeMs = buffer.getLong()

            // 读取输入开关标志位 (10个4字节长整型)
            val inputSwitchFlags = mutableListOf<Long>()
            for (i in 0 until 10) {
                buffer.position(OFFSET_INPUT_SWITCH_FLAGS + i * 4)
                inputSwitchFlags.add(buffer.getInt().toLong() and 0xFFFFFFFFL)
            }

            // 读取故障码 (各4字节长整型)
            buffer.position(OFFSET_HARDWARE_FAULT)
            val hardwareFaultCode = buffer.getInt().toLong() and 0xFFFFFFFFL

            buffer.position(OFFSET_SOFTWARE_FAULT)
            val softwareFaultCode = buffer.getInt().toLong() and 0xFFFFFFFFL

            // 读取设备信息 (各4字节长整型)
            buffer.position(OFFSET_DEVICE_ID)
            val deviceId = buffer.getInt().toLong() and 0xFFFFFFFFL

            buffer.position(OFFSET_SOFTWARE_VERSION)
            val softwareVersion = buffer.getInt().toLong() and 0xFFFFFFFFL

            buffer.position(OFFSET_HARDWARE_VERSION)
            val hardwareVersion = buffer.getInt().toLong() and 0xFFFFFFFFL

            // 读取标志位 (各1字节)
            buffer.position(OFFSET_RELAY_OUTPUT)
            val relayOutputFlag = buffer.get()

            buffer.position(OFFSET_RUNNING_FLAG)
            val runningFlag = buffer.get()

            buffer.position(OFFSET_DATA_TYPE)
            val dataType = buffer.get()

            // 创建并返回BeerMachineStatus对象
            return BeerMachineStatus(
                timestamp = Date(),
                temperature = temperature,
                beerBottleWeight = beerBottleWeight,
                outputBeerWeight = outputBeerWeight,
                bottlePressure = bottlePressure,
                co2Pressure = co2Pressure,
                motorPosition = motorPosition,
                flowCount = flowCount,
                runningTimeMs = runningTimeMs,
                inputSwitchFlags = inputSwitchFlags,
                hardwareFaultCode = hardwareFaultCode,
                softwareFaultCode = softwareFaultCode,
                deviceId = deviceId,
                softwareVersion = softwareVersion,
                hardwareVersion = hardwareVersion,
                relayOutputFlag = relayOutputFlag,
                runningFlag = runningFlag,
                dataType = dataType
            )
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }

    /**
     * 计算校验和
     * 根据协议，校验和为从第2个字节开始到数据长度+4结束的所有字节的和
     * @param data 数据包
     * @return 计算得到的校验和
     */
    private fun calculateChecksum(data: ByteArray): Byte {
        var sum = 0
        // 从第2个字节开始（索引1），到校验和字段前一个字节结束
        for (i in 1 until OFFSET_CHECKSUM) {
            sum += data[i].toInt() and 0xFF
        }
        return (sum and 0xFF).toByte()
    }

    /**
     * 打印数据包内容（用于调试）
     * @param data 数据包
     */
    fun printPacket(data: ByteArray) {
        println("数据包长度: ${data.size} 字节")
        println("头部: 0x${data[0].toInt() and 0xFF}")
        println("数据长度: ${data[1].toInt() and 0xFF}, ${data[2].toInt() and 0xFF}, ${data[3].toInt() and 0xFF}")
        println("温度: ${data[OFFSET_TEMPERATURE].toInt() and 0xFF}°C")
        println("酒瓶重量: ${ByteBuffer.wrap(data, OFFSET_WEIGHT1, 4).order(ByteOrder.LITTLE_ENDIAN).float}")
        println("出酒量: ${ByteBuffer.wrap(data, OFFSET_WEIGHT2, 4).order(ByteOrder.LITTLE_ENDIAN).float}")
        println("校验和: 0x${data[OFFSET_CHECKSUM].toInt() and 0xFF}")
        println("尾部: 0x${data[data.size - 2].toInt() and 0xFF}, 0x${data[data.size - 1].toInt() and 0xFF}")
    }
}
